#pragma once
#include "Encryptor.h"
#include "AESKey.h"
#include "AESBlock.h"

namespace AppliedCryptography
{
	namespace AES
	{
		namespace AC = AppliedCryptography;

		template<AC::AES::EKeySize TKeySize, AC::AES::EBlockSize TBlockSize = AC::AES::block128bit>
		class Encryptor : public AC::Encryptor<TKeySize, TBlockSize>
		{
		private:
			AC::AES::Key<TKeySize> _key;

		public:
			Encryptor() : AC::Encryptor<TKeySize, TBlockSize>()
			{ /*...*/ };

			virtual ~Encryptor()
			{ /*...*/ };

		public:
			virtual void SetKey(const AC::Key<TKeySize>& key)
			{
				_key.Set(key.Get());
			};

			virtual void Process(const AC::Block<TBlockSize>& plaintext, AC::Block<TBlockSize>& chyper) const
			{
				byte keyByte[TKeySize];
				byte plainByte[TBlockSize];
				byte chyperByte[TBlockSize];

				for(unsigned int i=0; i < TKeySize; i++)
					keyByte[i] = _key.Get().at(i);

				for(unsigned int i=0; i < TBlockSize; i++)
					plainByte[i] = plaintext.Get().at(i);

				CryptoPP::AES::Encryption aese(keyByte, TKeySize);
				aese.ProcessBlock(plainByte, chyperByte);

				chyper.Set(chyperByte);
			};

			virtual const AC::Key<TKeySize>& Key() const
			{
				return _key;
			};
		};
	};
};

